package api;

import helpers.GeneralHelper;
import helpers.ValidateHelper;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Date;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;

import javax.cache.Cache;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import library.PayFee;
import library.Utils;
import models.ApiConfigModel;
import models.BlockCustomerModel;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.NativeArray;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;

import com.google.appengine.api.urlfetch.HTTPHeader;
import com.google.appengine.api.urlfetch.HTTPMethod;
import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.appengine.api.urlfetch.URLFetchServiceFactory;
import com.google.gson.Gson;

import entities.ApiConfig;
import entities.BlockCustomer;

@SuppressWarnings("serial")
public class GetSpecialContentApi extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)
		throws IOException, ServletException {
		
		
		TreeMap<String, Object> result = new TreeMap<String, Object>();
		String charset = "UTF-8";
		
		String key = (String) request.getParameter("key");
		String c = (String) request.getParameter("c");
		String url = (String) request.getParameter("url");
		String t = (String) request.getParameter("type");
		
		try {
			if (c == null || key == null) {
				result.put("status", "error");
				result.put("message", "Api key or config id is not valid.");
			} else if (url == null || url.isEmpty() || !ValidateHelper.isUrl(url)) {
				result.put("status", "error");
				result.put("message", "Url is not valid.");
			} else {
				ApiConfigModel apiConfigModel = ApiConfigModel.getInstance();
				ApiConfig apiConfig = apiConfigModel.get(c);
				
				if (apiConfig == null) {
					result.put("status", "error");
					result.put("message", "This config can't not found on systems.");
				} else if (!apiConfig.getUserApi().equals(key)) {
					result.put("status", "error");
					result.put("message", "User Api Key is not valid.");
				} else {
					
					BlockCustomerModel blockCustomerModel = BlockCustomerModel.getInstance();
					BlockCustomer blockCustomer = blockCustomerModel.get(apiConfig.getUserBlog());
					
					if (blockCustomer == null) {
						TreeMap<String, String> dataMap = new TreeMap<String, String>();
						dataMap.put("url", url);
						
						/*********************    Get Content from url *********************/
						Document doc = null;
						String strContent="";
						String strTitle = "";
						
						doc = Jsoup.connect(url).get();
						charset = doc.outputSettings().charset().name();
		
						if(!"yes".equals(apiConfig.getActiveContentJs()))
						{
							try{
								strTitle = doc.select(apiConfig.getTitleSelecter()).text();
								doc = Jsoup.parse(doc.select(apiConfig.getContentSelecter()).toString());
								if(!apiConfig.getRemove_tag_a().equals("") && !apiConfig.getRemove_tag_a().isEmpty())
									doc.select(apiConfig.getRemove_tag_a()).remove();
								doc.select("script").remove();
								
								doc.select("a").attr("rel","nofollow");
								strContent = doc.select("body").html();
							} catch (Exception e) {
								e.printStackTrace();
								// TODO: handle exception
							}
							
						} else {
							try {
								Context context = Context.enter();
								
								ScriptableObject scope = context.initStandardObjects();
							    Scriptable that = context.newObject(scope);
							    Function fct = context.compileFunction(scope, apiConfig.getCustomSelecter(), "line ", 1, null);
							    Object result1 = fct.call(
							            context, scope, that, new Object[] {doc});
							    
							    
							    NativeArray arr = (NativeArray) Context.jsToJava(result1, NativeArray.class);
								
							    for (Object o : arr.getIds()) {
							        String index1 = (String)o;
							        
							        dataMap.put(index1, (String) arr.get(index1));
							    }
							    
							    strTitle = (String) arr.get("title");
								strContent = (String) arr.get("content");
								
							} catch (Exception e) {
								request.setAttribute("contentJs", e.getMessage());
								
								e.printStackTrace();
							}
						}
					
						strContent = strContent.replaceAll("&amp;", "&");
						
						doc = Jsoup.parse(strContent);
						
						strContent = Utils.cleanContent(strContent);
						
						if(apiConfig.getRemove_tag_a()!=null && apiConfig.getRemove_tag_a().equals("yes"))
						{
							strContent = Utils.removeTagA(strContent);
						}
		
						if(apiConfig.getSource().equals("yes"))
						{
							if(apiConfig.getSourcetype()!=null&&apiConfig.getSourcetype().equals("link"))
								strContent += "<div class='hfr-src'>Source : <a rel='nofollow' href='"+url+"' target='_blank'>"+url+"</a></div>";
							else
								strContent += "<div class='hfr-src'>Source : "+Utils.fomatDmain(url).replaceAll("[.]{1}", "[dot]")+"</div>";
						}
						
						doc = Jsoup.parse(strContent);
						
						if(apiConfig.getTypelink().equals("nofollow"))
						{
							doc.select("a").attr("rel","nofollow");
						}
						
						
						strContent = changeImg(doc, url, apiConfig.getSource_image());
						
						dataMap.put("title", strTitle);
						dataMap.put("content", strContent);
						
						
						/********************* End Get Content from url *********************/
						
						result.put("status", "success");
						result.put("data", dataMap);
						
						
						//Tru tien credit
						String note = "Pay 1 credit to get content: " + strTitle;
						if (strTitle.isEmpty()) {
							note = "Pay 1 credit to get content from url " + url;
						}
						PayFee.payFee(1, apiConfig.getUserBlog(), note);
					} else {
						result.put("status", "error");
						result.put("message", "You don't have enough credit to get content or your account has been block.");
					}
				}
			}
		} catch (Exception e) {
			result.put("status", "error");
			result.put("message", "Can't get content from this url " + url);
		}
		
		response.setCharacterEncoding(charset);
		
		if (t == null || !t.equals("xml")) {
			response.setContentType("application/json");
			String json = new Gson().toJson(result);
			response.getWriter().println(json);
		} else {
			response.setContentType("application/xml");
			String xml = getXml(result);
			response.getWriter().println(xml);
		}
	}
	
	public void doPost(HttpServletRequest request, HttpServletResponse response)
		throws IOException, ServletException {
		
		String t = (String) request.getParameter("type");
		
		TreeMap<String, Object> result = new TreeMap<String, Object>();
		result.put("status", "success");
		
		TreeMap<String, String> dataMap = new TreeMap<String, String>();
		dataMap.put("url", "http://www.techradar.com/reviews/phones/mobile-phones/iphone-5s-1179315/review");
		dataMap.put("title", "iPhone 5S review");
		dataMap.put("content", "<div itemprop=\"reviewBody\"> \n <div> \n <span>Recommended award</span> \n </div> \n <p>The iPhone 5S: a phone that looks like the <a href=\"http://www.techradar.com/reviews/phones/mobile-phones/iphone-5-1096004/review\" rel=\"nofollow\">iPhone 5</a>, but goes so much further under the hood. Is that going to be enough to impress the baying hoardes?</p> \n <p>We've been here before: the iPhone 'S' conundrum. The new phone comes along, taking the shell of the previous model, adds some new bits and pieces, and then claims to be an entirely new phone. </p> \n <div> \n <strong>Scores in depth<br /><br /> \n <figure> \n <img src=\"http://cdn0.mos.techradar.futurecdn.net//art/techradar/Reviews%20scores/Design/design_4-580-100.jpg\" width=\"580\" alt=\"Design\" /> \n </figure><br /> \n <figure> \n <img src=\"http://cdn0.mos.techradar.futurecdn.net//art/techradar/Reviews%20scores/Features/features_4.5-580-100.jpg\" width=\"580\" alt=\"Features\" /> \n </figure><br /> \n <figure> \n <img src=\"http://cdn1.mos.techradar.futurecdn.net//art/techradar/Reviews%20scores/Performance/performance_4.5-580-100.jpg\" width=\"580\" alt=\"Performance\" /> \n </figure><br /> \n <figure> \n <img src=\"http://cdn0.mos.techradar.futurecdn.net//art/techradar/Reviews%20scores/Usability/usability_4-580-100.jpg\" width=\"580\" alt=\"Usability\" /> \n </figure><br /> \n <figure> \n <img src=\"http://cdn2.mos.techradar.futurecdn.net//art/techradar/Reviews%20scores/Value/value_3.5-580-100.jpg\" width=\"580\" alt=\"Value\" /> \n </figure><br /><br /><br /><br /></strong> \n </div> \n <p>Which it is, of course. But also it isn't. Well, mostly is. To be sure, it's the kind of move that only Apple can pull off with any kind of conviction: the notion that it can take the same chassis, have a little tinker, throw in a new CPU, slightly better battery and camera, and call it an all-conquering device.</p> \n <p>But then again, such is the clamour to know all about it, is that such a bad move? There are literally millions of people the world over who can't wait to see what the next handset from Apple will be, and there was no surprise with the iPhone 5S.</p> \n <p>There are a few who question whether it's 'fair' to launch a phone and then append an 'S' to the same thing a year later - Apple's response would likely be that nobody is forcing you to buy the new hardware. And that's a fair point. Yes, this is a phone that bears far too many hallmarks of its predecessor. And yes, this is the third time Apple has done this.</p> \n <p>It's also managed to try to pop it onto the market complete as one of the most expensive smartphones out there, even on 3G plans. You'll be looking at post &pound;50 a month to get one without an upfront fee in the UK, and &pound;549 will be the price if you want the low end model, pushing all the way up to over &pound;700 for the 64GB variant.</p> \n <figure> \n <img src=\"http://cdn3.mos.techradar.futurecdn.net//art/mobile_phones/iPhone/iPhone%205S/Press/iPhone5s%20front-580-100.jpg\" width=\"580\" alt=\"iPhone 5S review\" /> \n </figure> \n <p>But if it was such a bad business move, if the market wasn't willing to accept such a thing, then Apple would have folded as a smartphone brand years ago... or at least been lagging behind the competition.</p> \n <p>That said, times are changing in the smartphone landscape. Where before Apple was able to just create the phone it wanted, and forget the competition in the knowledge that it wasn't going to have to worry about losing consumers to a competitor, now it's been forced to realise that there are at least four decent options for a consumer to think about if they want to get a rather good handset.</p> \n <p>Apple is obviously aware of this change, be it the aluminium unibody of the <a href=\"http://www.techradar.com/reviews/phones/mobile-phones/htc-one-1131862/review\" rel=\"nofollow\">HTC One</a>, the new fight into low-light cameras or the need for a strong processor as a headline to shout about. And to be fair, it's addressed these needs to some degree or other on the iPhone 5S.</p> \n <h3>iPhone 5S unboxing, in association with O2 Guru</h3> \n <p> <object width=\"580\" height=\"356\"> <param name=\"movie\" value=\"http://www.youtube.com/v/kUz3U2RzV9I&hl=en&fs=1\"></param> <param name=\"allowFullScreen\" value=\"true\"></param> <param name=\"allowscriptaccess\" value=\"always\"></param> <embed src=\"http://www.youtube.com/v/kUz3U2RzV9I&hl=en&fs=1\" type=\"application/x-shockwave-flash\" allowscriptaccess=\"always\" allowfullscreen=\"true\" width=\"580\" height=\"356\" /> </object> </p> \n <p>Be it the all-new Touch ID home button (which is excellent, more on that later), the huge jump in CPU power or the fact the camera has, once again, been improved no end, the new iPhone is clearly Apple's attempt at bringing as much as it can to the party without having to re-design the whole concept all over again.</p> \n <p>There are many that think releasing the same design twice is cheeky, and there are others who realise that sometimes there's no need for change. It's easy to fall into the former camp, and while Apple will happily point out it's not <em>forcing </em>anyone to buy its phones, its acutely aware the competition is now scarily strong and it needed to bring its best to stay relevant.</p> \n</div>\n<div class=\"hfr-src\">\n Source : techradar[dot]com\n</div>");
		
		result.put("data", dataMap);
		
		if (t == null || !t.equals("xml")) {
			response.setContentType("application/json");
			String json = new Gson().toJson(result);
			response.getWriter().println(json);
		} else {
			response.setContentType("application/xml");
			String xml = getXml(result);
			response.getWriter().println(xml);
		}
		
	}
	
	private String getXml(TreeMap<String, Object> rs) {
		String xml = "<?xml version=\"1.0\"?>";
		xml += "<result>";
		xml += "<status>" + rs.get("status") + "</status>";
		if (rs.get("message") != null) {
			xml += "<message>" + rs.get("message") + "</message>";
		}
		
		if (rs.get("data") != null) {
			
			TreeMap<String, String> dataMap = (TreeMap<String, String>) rs.get("data");
			
			xml += "<data>";
			
			for (Map.Entry<String, String> entry : dataMap.entrySet()) {
				xml += "<"+ entry.getKey() +">";
				if (entry.getKey().equals("content")) {
					xml += "<![CDATA[" + entry.getValue() + "]]>";
				} else {
					xml += entry.getValue();
				}
				xml += "</"+ entry.getKey() +">";
			}
			
			xml += "</data>";
		}
		
		
		xml += "</result>";
		
		return xml;
	}
	
	public static String changeImg(Document elements,String blogurl,String source_image) throws IOException
	{
		String element = elements.select("body").html();
		Elements img = elements.select("img");
		Elements a = elements.select("a");
		element = element.replaceAll("&amp;", "&");
		try {
			for(int i=0;i<a.size();i++)
			{
				String aa= a.eq(i).attr("href");
				if(!"".equals(aa))
				{
					int index = aa.indexOf("&u=");
					int end = aa.indexOf("&usg=");
					String aa1=aa;
	
					if (index != -1) {
						aa1=aa.substring(index+3, end);
					}
					String imageUrl = Utils.fomatLink(aa1, blogurl);
					
					element = element.replace(aa, imageUrl);
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		
		try {
			URLFetchService fetcher = URLFetchServiceFactory.getURLFetchService();
			for(int i=0;i<img.size();i++)
			{
				String im= img.eq(i).attr("src");
				if(!"".equals(im))
				{
					String imageUrl = Utils.fomatLink(im, blogurl);

					if(source_image!=null&&source_image.equals("cdn"))
					{
						File file = new File(imageUrl.replaceAll("[ ]{1}", "%20"));  			
						
	
						String path_image="http://cdn.as7.org/";
						
						String file_name = Utils.md5(new Random().nextInt(1000)+new Date().getTime()+"")+"_"+file.getName().replaceAll("[?]{1}[\\w\\W]*$", "");
						file_name=file_name.replaceAll("[ ]+", "").replaceAll("%20", "").replaceAll("[^\\w.]+", "");
						
						String destinationFile = path_image+file_name;
						
						element = element.replace(im, destinationFile);
					
						try {
							URL url = new URL("http://hatforrent-image.appspot.com/upload-image");
							try {
								HTTPRequest request = new HTTPRequest(url, HTTPMethod.POST);
								
					            request.setHeader(new HTTPHeader("Content-Type", "application/x-www-form-urlencoded"));
					            String params = "src="+ Utils.EncodeString(imageUrl.replaceAll("[ ]{1}", "%20")) +
					            				"&file="+ Utils.EncodeString(file_name);
					            request.setPayload(params.getBytes());
					            
					            fetcher.fetchAsync(request);
							} catch (Exception e) {
								e.printStackTrace();
							}
							
						} catch (Exception e) {
							e.printStackTrace();
						}
					} else {
						element = element.replace(im, imageUrl);
					}
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		
		return element;
	}
	
}
